#include "truck.h"
#include "../framework.h"
#include "crate.h"
#include "loadArea.h"
#include <iostream>

const unsigned int Truck::movingTicks = 21;
const float Truck::maxSpeed = 10.0f;
const float Truck::accel = 0.48f;
const float Truck::rotationAngle = 0.01f;

Truck::Truck(Rectangle chasisRec,Rectangle loadAreaRec)
	:	SceneObject(),
		Solid(Rectangle(loadAreaRec.x1+chasisRec.centerX(),loadAreaRec.x2+chasisRec.centerX(),
						loadAreaRec.y1+chasisRec.centerY(),loadAreaRec.y2+chasisRec.centerY()),true){
	this->addObject(Chasis::name(),new Chasis(chasisRec,loadAreaRec));
	this->addObject(Tire::name(),new Tire());
	this->loaded = false;
	this->leaving = false;
}

Truck::~Truck(){
	if(loaded)
		this->getObject(Crate::name());
}

void Truck::draw(){
	Framework& fr = Framework::instance();

	fr.pipeline.pushMatrix();
		this->findObject(Chasis::name()).draw();

		Rectangle chasisRec = ( this->findObject(Chasis::name()) ).getDimensions();
		Rectangle loadAreaRec = ( this->findObject(Chasis::name()).findObject(LoadArea::name()) ).getDimensions();
		fr.pipeline.translate(chasisRec.centerX(),chasisRec.centerY());
		fr.pipeline.pushMatrix();
			fr.pipeline.translate(0.0f,chasisRec.height()/2);
			fr.pipeline.escale(chasisRec.width()/40,chasisRec.width()/40);
			this->findObject(Tire::name()).draw();
		fr.pipeline.popMatrix();

		fr.pipeline.pushMatrix();
			fr.pipeline.translate(loadAreaRec.centerX(),chasisRec.height()/2);
			fr.pipeline.escale(chasisRec.width()/40,chasisRec.width()/40);
			this->findObject(Tire::name()).draw();
		fr.pipeline.popMatrix();
	fr.pipeline.popMatrix();
}

void Truck::goLeftLimit(){
	if(	this->state.motion==Truck::STOPPED ) {
		this->state.motion=Truck::ACCEL;
		this->state.dir=Truck::LEFT;
	}
}

void Truck::goRightLimit(){
	if(	this->state.motion==Truck::STOPPED ) {
		this->state.motion=Truck::ACCEL;
		this->state.dir=Truck::RIGHT;
	}
}

bool Truck::isStopped(){
	return (this->state.motion==Truck::STOPPED);
}

bool Truck::isMoving(){
	return (this->state.motion!=Truck::STOPPED);
}

void Truck::timeStep(){
	switch(this->state.motion){
		case Truck::ACCEL:
			this->speed += Truck::accel*this->state.dir;
			break;
		case Truck::DESAC:
			this->speed -= Truck::accel*this->state.dir;
			break;
		case Truck::MOVING:
			this->dimensions.translate(this->speed,0.0f);
			this->state.currTicks++;
			if(this->state.currTicks==Truck::movingTicks){
				this->state.currTicks = 0;
				this->state.motion = Truck::DESAC;
			}
			break;
		case Truck::STOPPED:
			break;
		default:
			break;
	}

	if(fabs(this->speed)>Truck::maxSpeed){
		this->state.motion = Truck::MOVING;
		this->speed = Truck::maxSpeed*this->state.dir;
	}else if( ((this->speed)<0&&this->state.dir==RIGHT) ||
			  ((this->speed)>0&&this->state.dir==LEFT)){
		this->state.motion = Truck::STOPPED;
		this->speed = 0;

		if(this->state.dir==Truck::LEFT && leaving){
			this->findObject(Crate::name()).setKill(true);
			this->getObject(Crate::name());
			this->goRightLimit();
			this->loaded=false;
			this->leaving=false;
		}
	}

	this->move(this->speed,0.0f);
}

void Truck::move(float dx,float dy){
	( this->findObject(Chasis::name()) ).move(dx,0.0f);
	this->getSize().translate(dx,0.0f);

	dynamic_cast<Tire&>(this->findObject(Tire::name())).addRotationAngle(Truck::rotationAngle*dx);

	if(loaded){
		this->findObject(Crate::name()).move(dx,0.0f);
	}
}

void Truck::notifyCollision(Solid* obj){
	this->addObject(Crate::name(),static_cast<Crate*>(obj));
	this->goLeftLimit();
	this->loaded=true;
	this->leaving=true;
}
